package com.fadadianqi.logistics.inventory.service;

import com.fadadianqi.commons.PrimaryKeyCreator;
import com.fadadianqi.goods.model.Goods;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.logistics.inventory.dao.BatchDAO;
import com.fadadianqi.logistics.inventory.dao.DispatchLogDAO;
import com.fadadianqi.logistics.inventory.dao.ItemDAO;
import com.fadadianqi.logistics.inventory.model.Batch;
import com.fadadianqi.logistics.inventory.model.DispatchLog;
import com.fadadianqi.logistics.inventory.model.Item;
import com.fadadianqi.logistics.inventory.model.Storehouse;
import com.yeqiangwei.commons.util.Pagination;
import com.yeqiangwei.commons.util.ValidatorHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 录入库存
 *
 * @author aroot
 *         <p/>
 *         //事务传播属性
 * @Transactional(propagation=Propagation.REQUIRED) //如果有事务,那么加入事务,没有的话新建一个(不写的情况下)
 * @Transactional(propagation=Propagation.NOT_SUPPORTED) //容器不为这个方法开启事务
 * @Transactional(propagation=Propagation.REQUIRES_NEW) //不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
 * @Transactional(propagation=Propagation.MANDATORY) //必须在一个已有的事务中执行,否则抛出异常
 * @Transactional(propagation=Propagation.NEVER) //必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
 * @Transactional(propagation=Propagation.SUPPORTS) //如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
 * @Transactional(propagation=Propagation.NESTED)
 * @Transactional (propagation = Propagation.REQUIRED, readOnly=true) //readOnly=true只读,不能更新,删除
 * @Transactional (propagation = Propagation.REQUIRED, timeout=30)//设置超时时间
 * @Transactional (propagation = Propagation.REQUIRED, isolation=Isolation.DEFAULT)//设置数据库隔离级别
 */
@Service
public class InventoryService {


    public com.fadadianqi.logistics.inventory.model.Item getById(String inventoryId) {
        return itemDAO.getById(inventoryId);
    }

    public com.fadadianqi.logistics.inventory.model.Item getNormalItemByGoodsId(String goodsId) {
        return itemDAO.getNormalByGoodsId(goodsId);
    }

    public com.fadadianqi.logistics.inventory.model.Item getNormalItemByGoodsIdAndStorehouseId(
            String goodsId, String storehouseId) {
        return itemDAO.getNormalItemByGoodsIdAndStorehouseId(goodsId, storehouseId);
    }

    public Item getNormalItemByBatchId(String batchId) {
        return itemDAO.getNormalItemByBatchId(batchId);
    }

    public int countStatusNormalByGoodsId(String goodsId) {
        return itemDAO.countNormalStatusByGoodsId(goodsId);
    }

    /**
     * @param batchId
     * @return
     */
    public int countNormalStatusByBatchId(String batchId) {
        return itemDAO.countNormalStatusByBatchId(batchId);
    }

    /**
     * @param brandId
     * @param categoryId
     * @param status
     */
    public int countByBrandIdAndCategoryId(String brandId, String categoryId,
                                           int status) {
        return itemDAO.countByBrandIdAndCategoryId(brandId, categoryId, status);
    }

    public int countByGoodsIdAndStorehouseIdAndStatus(String goodsId, String storehouseId, int status) {
        if (ValidatorHelper.isEmpty(goodsId)) {
            return 0;
        }
        return itemDAO.countByGoodsIdAndStorehouseIdAndStatus(goodsId, storehouseId, status);
    }

	/*public void dispatchStorehouse(String goodsId, String fromId,
            String storehouseId) {
		itemDAO.dispatchStorehouse(goodsId, fromId, storehouseId);
	}*/

    /**
     * @param goodsId
     * @param fromId
     * @param storehouseId
     * @param num
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
    public void dispatchStorehouse(String goodsId, String fromId,
                                   String storehouseId, int num) {
        if (num <= 0) {
            return;
        }
        Pagination pagination = new Pagination(1, num);
        List<Item> list = itemDAO.findByGoodsIdAndStorehouseIdAndStatus(
                goodsId, fromId, Item.STATUS_NORMAL, pagination);
        if (ValidatorHelper.isEmpty(list)) {
            return;
        }
        Goods goods = goodsService.getGoodsById(goodsId);
        for (Item item : list) {
            item.setStorehouseId(storehouseId);
            itemDAO.update(item);
        }
        DispatchLog log = new DispatchLog();
        log.setId(PrimaryKeyCreator.create());
        log.setAddTime(new Date());
        log.setBrandId(goods.getBrandId());
        log.setCategoryId(goods.getCategoryId());
        log.setFromStorehouseId(fromId);
        log.setToStorehouseId(storehouseId);
        log.setGoodsId(goods.getId());
        log.setNum(num);
        log.setStaffId(null);
        dispatchLogDAO.create(log);
        updateStorehouesTotal(fromId, goodsId);
        updateStorehouesTotal(storehouseId, goodsId);
    }

    /**
     * 更新库房商品的现存数量
     *
     * @param storehouseId
     * @param goodsId
     */
    public void updateStorehouesTotal(String storehouseId, String goodsId) {
        if (ValidatorHelper.isEmpty(storehouseId)
                || ValidatorHelper.isEmpty(goodsId)) {
            return;
        }
        int total = countByGoodsIdAndStorehouseIdAndStatus(
                goodsId, storehouseId, Item.STATUS_NORMAL);
        Storehouse t = storehouseService.getStorehouseById(storehouseId);
        if (t != null) {
            t.setTotal(total);
            storehouseService.update(t);
        }
    }

    /**
     * .
     *
     * @param brandId
     * @param categoryId
     * @param status
     * @return
     */
    public double sumPurchaseByBrandIdAndCategoryId(String brandId, String categoryId,
                                                    int status) {
        return itemDAO.sumPurchaseByBrandIdAndCategoryId(brandId, categoryId,
                status);
    }

    /**
     * @param brandId
     * @param categoryId
     * @param status
     * @return
     */
    public double sumCostByBrandIdAndCategoryId(String brandId, String categoryId,
                                                int status) {
        return itemDAO.sumCostByBrandIdAndCategoryId(brandId, categoryId,
                status);
    }

    /**
     * 入库
     *
     * @param inventory 库存条目
     * @param total     入库总数
     * @throws Exception
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void store(Item item, String storehouseId, int total) throws Exception {
        if (ValidatorHelper.isEmpty(item.getGoodsId())) {
            throw new IllegalArgumentException();
        }
        if (item.getAddTime() == null) {
            item.setAddTime(new Date());
        }
        item.setLastUpdateTime(new Date());

        Batch batch = new Batch();
        batch.setCost(item.getCost());
        batch.setDiscountRate(item.getDiscountRate());
        batch.setPurchase(item.getPurchase());
        batch.setTrade(item.getTrade());
        batch.setMemo(item.getMemo());
        batch.setId(PrimaryKeyCreator.create());
        batch.setTotal(total);
        batch.setAddTime(item.getAddTime());
        batch.setGoodsId(item.getGoodsId());
        Goods goods = goodsService.getGoodsById(item.getGoodsId());
        batch.setBrandId(goods.getBrandId());
        batch.setCategoryId(goods.getCategoryId());
        batch.setStorehouseId(storehouseId);
        batchDAO.create(batch);

        for (int i = 0; i < total; i++) {
            goods.setLatestStore(item.getAddTime());
            goods.setRecentlyUpdate(new Date());
            goodsService.updateGoodsTimeUtils(goods);
            item.setId(PrimaryKeyCreator.create());
            item.setBatchId(batch.getId());
            item.setBrandId(goods.getBrandId());
            item.setCategoryId(goods.getCategoryId());
            item.setStorehouseId(batch.getStorehouseId());
            itemDAO.create(item);
        }

        updateStorehouesTotal(storehouseId, item.getGoodsId());
    }

    public void doBackReturn(String batchId, int count) {
        Batch batch = batchDAO.getById(batchId);
        for (int i = 0; i < count; i++) {
            Item item = getNormalItemByGoodsId(batch.getGoodsId());
            if (item != null) {
                item.setStatus(Item.STATUS_RETURN);
                update(item);
            }
        }
    }

    /**
     * 根据ID修改库存记录
     *
     * @param inventory
     * @param ids
     */
    public void update(Item item) {
        if (ValidatorHelper.isEmpty(item.getGoodsId())
                || ValidatorHelper.isEmpty(item.getId())) {
            throw new IllegalArgumentException();
        }
        itemDAO.update(item);
    }

    public List<Item> findByBatchId(String batchId) {
        return itemDAO.findByBatchId(batchId);
    }

    public List<Item> findLeCost(Double maxCost) {
        return itemDAO.findLeCost(maxCost);
    }

    public Batch getBatchById(String id) {
        return batchDAO.getById(id);
    }

    @Autowired
    private BatchDAO batchDAO;

    @Autowired
    private ItemDAO itemDAO;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private DispatchLogDAO dispatchLogDAO;

    @Autowired
    private StorehouseService storehouseService;
}
